home *** CD-ROM | disk | FTP | other *** search
/ Aminet 39 / Aminet 39 (2000)(Schatztruhe)[!][Oct 2000].iso / Aminet / mus / play / DelfMPEG.lha / DelfMPEG / src / DelfMPEG.c < prev    next >
C/C++ Source or Header  |  2000-07-27  |  41KB  |  1,206 lines

  1. /*****************************************************************************
  2.  
  3.     DelfMPEG - MPEG audio player for Delfina DSP
  4.     Copyright (C) 1999, 2000  Michael Henke
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20. *****************************************************************************/
  21.  
  22.  
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25. #include <proto/asyncio.h>
  26. #include <proto/timer.h>
  27. #include <proto/reqtools.h>
  28. #include <exec/interrupts.h>
  29. #include <exec/execbase.h>
  30. #include <exec/memory.h>
  31. #include <exec/libraries.h>
  32. #include <libraries/asyncio.h>
  33. #include <devices/timer.h>
  34. #include <libraries/reqtools.h>
  35. #include <stdlib.h>
  36. #include <math.h>
  37. #include <stdio.h>
  38.  
  39. static UBYTE version[]="$VER: DelfMPEG 0.6 (Thu 27-Jul-2000)";
  40. static UBYTE template[]=
  41.  "FILES/M,-V=VERBOSE/S,-N=NOPLAY/S,-T=SHOWTAG/S,-NL=NOFASTL/S,-NP=NOFASTP/S,"
  42.  "-F=FRAMEBUF/K/N,-A=ASYNCBUF/K/N,-FF=FFSKIP/K/N,-NT=NOTIMER/S,-M=MONO/S,"
  43.  "-S=STRICT/S,-D=DACRATE/K/N,-VOL=VOLUME/K/N,AREXX/S";
  44.  
  45. #define DEFAULT_FRAMEBUF    100
  46. #define DEFAULT_ASYNCBUF    128
  47. #define DEFAULT_FFSKIP      10
  48.  
  49. struct loadbuf {
  50.     ULONG header;
  51.     UWORD framesize, delfcopysize, crc, III_main_data_size;
  52.     UBYTE layer, mode, modext, freq, errprot, br_ind, II_jsbound, II_translate;
  53.     struct loadbuf *next;
  54.     UBYTE data[1728];   /* max: layer II, 384 kbps, 32 kHz -> 1728-4 bytes */
  55. };
  56.  
  57. struct loadbuf *framebuf0=NULL, *curr_load, *curr_play;
  58. LONG framebuf0size=0;
  59.  
  60. static ULONG mpg_freq[4]={44100,48000,32000,0};
  61. static UBYTE *mpg_modename[4]={"stereo","j-stereo","dual-ch","single-ch"};
  62. static UBYTE *mpg_layername[3]={"I","II","III"};
  63. static UWORD mpg_bitrate[3][16]=
  64.         { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, /* I */
  65.           {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},   /* II */
  66.           {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0} }; /* III */
  67. static UWORD mpg_translate[3][2][16] =
  68.            { { { 0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0 } ,    /* 44100 stereo */
  69.                { 0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0 } } ,  /* 44100 mono   */
  70.              { { 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 } ,    /* 48000 stereo */
  71.                { 0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0 } } ,  /* 48000 mono   */
  72.              { { 0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0 } ,    /* 32000 stereo */
  73.                { 0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0 } } }; /* 32000 mono   */
  74. static UWORD mpg_sblimit[4]={27,30,8,12};
  75.  
  76. static ULONG ID3v1_TAG;
  77. UBYTE ID3v1_buffer[142];
  78.  
  79. /** static LONG pow43tab[8206]; **/
  80. #include "MP3_pow43tab.h"
  81. /** static LONG quantab[512]; **/
  82. #include "MP3_quantab.h"
  83.  
  84. static UWORD bitres_offset, bitres_ok;
  85. static UBYTE bitres_buffer[4096];
  86.  
  87. #define MPG_MD_STEREO           0
  88. #define MPG_MD_JOINT_STEREO     1
  89. #define MPG_MD_DUAL_CHANNEL     2
  90. #define MPG_MD_MONO             3
  91. #define HDR_MPEG1               0xfff80000
  92. #define HDR_CONSTANT            0x00060c00  /* layer, sampling frequency */
  93. #define ID3V1                   0x54414700  /* TAG */
  94. #define ID3V2                   0x49443300  /* ID3 */
  95. #define XING_FLAG_FRAMES        1
  96. #define XING_FLAG_BYTES         2
  97. #define XING_FLAG_TOC           4
  98.  
  99. static UBYTE *delfina_name[8]=
  100.     { "Classic","Lite","Pro","1200","Plus","UNKNOWN","UNKNOWN","UNKNOWN" };
  101.  
  102. extern struct DelfObj DSP56K_PCM;
  103. extern struct DelfObj DSP56K_MP2;
  104. extern struct DelfObj DSP56K_MP3;
  105.  
  106. #include <libraries/delfina.h>
  107. #include "PCM.h"
  108. #include "MP2.h"
  109. #include "MP3.h"
  110.  
  111. extern struct ExecBase *SysBase;
  112. struct Library *DelfinaBase=NULL;
  113. struct Library *AsyncIOBase=NULL;
  114. struct Library *TimerBase=NULL;
  115. struct ReqToolsBase *ReqToolsBase=NULL;
  116.  
  117. struct AsyncFile *file;
  118. struct FileInfoBlock *fib=NULL;
  119. struct TagItem tag_done={TAG_DONE};
  120. UBYTE rtfilename[128]={0};
  121. struct Task *mytask;
  122. ULONG bytes_total, bytes_loaded, buffers_filled, buffers_missed;
  123. ULONG prevheader, currheader, frames_loaded, frames_played;
  124. ULONG setpos_start, setpos_framesize;
  125. ULONG decoder_busy, maindata_err, frames_js;
  126. struct Interrupt delfint={0};
  127. struct DelfPrg *prg_pcm=NULL, *prg_mp2=NULL, *prg_mp3=NULL;
  128. struct DelfModule *mod_pcm=NULL;
  129. DELFPTR mem_il_mp2=NULL, mem_ip_mp2=NULL, mem_y_mp3_quantab=NULL;
  130. DELFPTR mem_il_mp3=NULL, mem_ip_mp3=NULL, mem_x_mp3_ro=NULL;
  131. ULONG key=0;
  132.  
  133. UWORD *gb_pt, gb_buf, gb_num;
  134.  
  135. UBYTE xing_toc[100];
  136. ULONG xingvbr, xing_flags, xing_frames;
  137. ULONG channels,mono,freq,layer,pause,noplay,showtag,rexxmode;
  138. ULONG verbose, ende, havetag, nofastl, nofastp, notimer, forcemono, strict;
  139. LONG framebuf, asyncbuf, ffskip, dacrate, volume;
  140. int rc=0;
  141.  
  142. /**
  143. *** in arexx.c
  144. **/
  145. /* funtions */
  146. char *initRexx(void);
  147. void cleanupRexx(void);
  148. void handleRexx(void);
  149. /* variables */
  150. extern char *rexxfilename[2];
  151. extern char *portname;
  152. extern WORD rexxstatus, rexxerror;
  153. extern char rexxfiletypebuf[512];
  154. extern ULONG rexxduration, rexxposition;
  155.  
  156.  
  157.  
  158. /*
  159. **
  160. ** layer III - bit reservoir handling **
  161. **
  162. */
  163. UWORD BitReservoir(struct loadbuf *buf)
  164. {
  165.     UWORD main_data_begin, i;
  166.     UBYTE *p0, *p1;
  167.     p1= &buf->data[0];
  168.     main_data_begin= (UWORD)(*p1)<<1 | (UWORD)(*(p1+1))>>7;
  169.     /*
  170.     ** copy side information **
  171.     */
  172.     p0= &bitres_buffer[0];
  173.     for(i=32; i>0; i--) *p0++= *p1++;
  174.     /*
  175.     ** copy previous main_data **
  176.     */
  177.     p0++; /* &bitres_buffer[33] */
  178.     if(bitres_offset>=main_data_begin)
  179.     {
  180.         bitres_ok=1;
  181.         p1=p0+bitres_offset-main_data_begin;
  182.         for(i=main_data_begin; i>0; i--) *p0++= *p1++;
  183.         bitres_offset=main_data_begin;
  184.     }
  185.     else
  186.     {
  187.         bitres_ok=0;            /* not enough data in reservoir */
  188.         p0+=bitres_offset;
  189.     }
  190.     /*
  191.     ** copy current main_data **
  192.     */
  193.     i= mono ? 17 : 32;          /* side info length */
  194.     p1= &buf->data[i];          /* begin of main_data area */
  195.     i= buf->delfcopysize-i;     /* mainslots */
  196.     bitres_offset+= i;
  197.     for(; i>0; i--) *p0++= *p1++;
  198.     return(bitres_ok);
  199. }
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206. /*
  207. **
  208. ** Delfina interrupt server **
  209. **
  210. */
  211. void __saveds IntServer(void)
  212. {
  213.     if(pause)
  214.     {
  215.         /*
  216.         ** mute **
  217.         */
  218.         Delf_Run( prg_pcm->prog+PROG_PCM_MUTE, 0, DRUNF_ASYNCH, 0, 0, 0, 0 );
  219.     }
  220.     else
  221.     {
  222.         if(buffers_filled>0)
  223.         {
  224.             switch(layer)
  225.             {
  226.             case 2:
  227.                 if( !Delf_Peek( prg_mp2->ydata+DATY_MP2_BUSY,DMEMF_YDATA ) )
  228.                 {
  229.                     /*
  230.                     ** send framedata to Delfina and launch MP2 decoder **
  231.                     */
  232.                     Delf_CopyMem( &curr_play->data[0],
  233.                                   (void*)(prg_mp2->xdata+DATX_MP2_INBUF),
  234.                                   (ULONG)curr_play->delfcopysize,
  235.                                   DCPF_FROM_AMY|DCPF_XDATA|DCPF_24BIT );
  236.                     Delf_Run( prg_mp2->prog+PROG_MP2_DECODE, 0, DRUNF_ASYNCH,
  237.                               mono,
  238.                               Delf_Peek(prg_pcm->ydata+DATY_PCM_BUFPTR,DMEMF_YDATA),
  239.                               (ULONG)curr_play->II_translate,
  240.                               (ULONG)curr_play->II_jsbound );
  241.                     frames_played++;
  242.                     buffers_filled--;
  243.                     curr_play=curr_play->next;
  244.                 }
  245.                 else decoder_busy++;
  246.                 break;
  247.             case 3:
  248.                 if( !Delf_Peek( prg_mp3->ydata+DATY_MP3_BUSY,DMEMF_YDATA ) )
  249.                 {
  250.                     /*
  251.                     ** send framedata to Delfina and launch MP3 decoder **
  252.                     */
  253.                     if(bitres_ok)
  254.                     {
  255.                         Delf_CopyMem( &bitres_buffer[0],
  256.                                       (void*)(prg_mp3->xdata+DATX_MP3_INBUF),
  257.                                       (ULONG)curr_play->III_main_data_size+33,
  258.                                       DCPF_FROM_AMY|DCPF_XDATA|DCPF_24BIT );
  259.                         Delf_Run( prg_mp3->prog+PROG_MP3_DECODE, 0, DRUNF_ASYNCH,
  260.                                   mono,
  261.                                   Delf_Peek(prg_pcm->ydata+DATY_PCM_BUFPTR,DMEMF_YDATA),
  262.                                   (ULONG)curr_play->modext,
  263.                                   0 );
  264.                     }
  265.                     else maindata_err++;
  266.                     frames_played++;
  267.                     buffers_filled--;
  268.                     curr_play=curr_play->next;
  269.                     if(buffers_filled>0) BitReservoir(curr_play);
  270.                 }
  271.                 else decoder_busy++;
  272.                 break;
  273.             default:
  274.                 break;
  275.             }
  276.         }
  277.         else if(frames_loaded>1) buffers_missed++;
  278.     }
  279. }
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287. void initPCM(void)
  288. {
  289.     if(!prg_pcm) return;
  290.     Delf_Run(prg_pcm->prog+PROG_PCM_INIT, 0, 0,
  291.             (ULONG)(forcemono?1:mono),
  292.             (volume>100) ? (volume*0x7fffff)/200 : (volume*0x400000)/100,
  293.             freq, 0 );
  294. }
  295.  
  296.  
  297. /*
  298. **
  299. ** allocate Delfina resources **
  300. **
  301. */
  302. int InitDelfina(void)
  303. {
  304.     if(noplay) return(0);
  305.     if(!(prg_pcm=Delf_AddPrg(&DSP56K_PCM)))
  306.     {
  307.         printf("**not enough Delfina memory\n");
  308.         return(0);
  309.     }
  310.     initPCM();
  311.     switch(layer)
  312.     {
  313.         case 2:
  314.             if(!nofastl)
  315.                 mem_il_mp2=Delf_AllocMem(INTL_MP2_DATL, DMEMF_LDATA|DMEMF_INTERNAL|DMEMF_ALIGN_64);
  316.             if(!nofastp)
  317.                 mem_ip_mp2=Delf_AllocMem(INTP_MP2_PROG, DMEMF_PROG|DMEMF_INTERNAL);
  318.             if(!(prg_mp2=Delf_AddPrg(&DSP56K_MP2)))
  319.             {
  320.                 printf("**not enough Delfina memory\n");
  321.                 return(0);
  322.             }
  323.             Delf_Run(prg_mp2->prog+PROG_MP2_INIT, 0, 0,
  324.                      mem_il_mp2, mem_ip_mp2, 0, 0);
  325.             if((!mem_il_mp2 && !nofastl) || (!mem_ip_mp2 && !nofastp))
  326.             {
  327.                 printf("**warning: not enough internal DSP memory\n"
  328.                        "  (the decoder might run too slowly and produce \"jerky\" sound)\n");
  329.             }
  330.             Delf_Poke(prg_mp2->ydata+DATY_MP2_FORCEMONO, DMEMF_YDATA, forcemono);
  331.             break;
  332.         case 3:
  333.             if(!nofastl)
  334.                 mem_il_mp3=Delf_AllocMem(INTL_MP3_DATL, DMEMF_LDATA|DMEMF_INTERNAL|DMEMF_ALIGN_64);
  335.             if(!nofastp)
  336.                 mem_ip_mp3=Delf_AllocMem(INTP_MP3_PROG, DMEMF_PROG|DMEMF_INTERNAL);
  337.             mem_x_mp3_ro=Delf_AllocMem(EXTX_MP3_RO,DMEMF_XDATA);
  338.             mem_y_mp3_quantab=Delf_AllocMem(EXTY_MP3_QUANTAB,DMEMF_YDATA);
  339.             prg_mp3=Delf_AddPrg(&DSP56K_MP3);
  340.             if(!prg_mp3 || !mem_x_mp3_ro || !mem_y_mp3_quantab)
  341.             {
  342.                 printf("**not enough Delfina memory\n");
  343.                 return(0);
  344.             }
  345.             Delf_CopyMem(pow43tab, (void*)(prg_mp3->ydata+DATY_MP3_POW43TAB),
  346.                          8206*4, DCPF_FROM_AMY|DCPF_YDATA|DCPF_32BIT);
  347.             Delf_CopyMem(quantab,  (void*)mem_y_mp3_quantab,
  348.                          512*4,  DCPF_FROM_AMY|DCPF_YDATA|DCPF_32BIT);
  349.             Delf_Run(prg_mp3->prog+PROG_MP3_INIT, 0, 0,
  350.                      mem_il_mp3, mem_ip_mp3,
  351.                      (ULONG)curr_play->freq,
  352.                      (ULONG)mem_x_mp3_ro);
  353.             if((!mem_il_mp3 && !nofastl) || (!mem_ip_mp3 && !nofastp))
  354.             {
  355.                 printf("**warning: not enough internal DSP memory\n"
  356.                        "  (the decoder might run too slowly and produce \"jerky\" sound)\n");
  357.             }
  358.             Delf_Poke(prg_mp3->xdata+DATX_MP3_QUANTAB_P, DMEMF_XDATA, mem_y_mp3_quantab);
  359.             Delf_Poke(prg_mp3->ydata+DATY_MP3_FORCEMONO, DMEMF_YDATA, forcemono);
  360.             break;
  361.         default:
  362.             printf("**layer %d is not supported\n",layer);
  363.             return(0);
  364.     }
  365.     delfint.is_Code=(void(*)(void))IntServer;
  366.     if (!(key=Delf_AddIntServer(prg_pcm->prog+PROG_PCM_INTKEY,&delfint)))
  367.     {
  368.         printf("**couldn't create interrupt server\n");
  369.         return(0);
  370.     }
  371.     if(!(mod_pcm=Delf_AddModule(DM_Inputs, 0,
  372.                                 DM_Outputs, 1,
  373.                                 DM_Code, prg_pcm->prog+PROG_PCM_MODULE,
  374.                                 DM_Freq, dacrate?dacrate*1000:freq,
  375.                                 DM_Name, "DelfMPEG", 0)))
  376.     {
  377.         printf("**couldn't create DelfModule\n");
  378.         return(0);
  379.     }
  380.     return(1);
  381. }
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389. /*
  390. **
  391. ** free Delfina resources **
  392. **
  393. */
  394. void CleanupDelfina(void)
  395. {
  396.     Delay(10);
  397.     if(mod_pcm) {Delf_RemModule(mod_pcm); mod_pcm=NULL;}
  398.     if(key)     {Delf_RemIntServer(key); key=0;}
  399.     if(prg_mp2) {Delf_RemPrg(prg_mp2); prg_mp2=NULL;}
  400.     if(prg_mp3) {Delf_RemPrg(prg_mp3); prg_mp3=NULL;}
  401.     if(prg_pcm) {Delf_RemPrg(prg_pcm); prg_pcm=NULL;}
  402.     if(mem_il_mp2) {Delf_FreeMem(mem_il_mp2,DMEMF_LDATA|DMEMF_INTERNAL); mem_il_mp2=NULL;}
  403.     if(mem_ip_mp2) {Delf_FreeMem(mem_ip_mp2,DMEMF_PROG |DMEMF_INTERNAL); mem_ip_mp2=NULL;}
  404.     if(mem_il_mp3) {Delf_FreeMem(mem_il_mp3,DMEMF_LDATA|DMEMF_INTERNAL); mem_il_mp3=NULL;}
  405.     if(mem_ip_mp3) {Delf_FreeMem(mem_ip_mp3,DMEMF_PROG |DMEMF_INTERNAL); mem_ip_mp3=NULL;}
  406.     if(mem_x_mp3_ro) {Delf_FreeMem(mem_x_mp3_ro,DMEMF_XDATA); mem_x_mp3_ro=NULL;}
  407.     if(mem_y_mp3_quantab) {Delf_FreeMem(mem_y_mp3_quantab,DMEMF_YDATA); mem_y_mp3_quantab=NULL;}
  408. }
  409.  
  410.  
  411.  
  412.  
  413.  
  414.  
  415. UWORD GetBits(UWORD num)
  416. {
  417.     UWORD val=0;
  418.     for(; num>0; num--)
  419.     {
  420.         if(gb_num==0)
  421.         {
  422.             gb_buf= *gb_pt++;
  423.             gb_num= 16;
  424.         }
  425.         gb_num--;
  426.         val+= val;
  427.         val|= (gb_buf>>gb_num)&1;
  428.     }
  429.     return(val);
  430. }
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437. UWORD CheckHeader(struct loadbuf *lb)
  438. {
  439.     UWORD result=0;
  440.  
  441.     /** let's ignore these header infos (we don't need them here)
  442.     *** ->version, ->extension, ->copyright, ->original, ->emphasis **/
  443.     lb->header  = currheader;
  444.     lb->layer   = 4-((currheader>>17)&0x3);
  445.     lb->mode    = ((currheader>>6)&0x3);
  446.     lb->modext  = ((currheader>>4)&0x3);
  447.     lb->br_ind  = ((currheader>>12)&0xf);
  448.     lb->freq    = ((currheader>>10)&0x3);
  449.     lb->errprot = ((currheader>>16)&0x1)^0x1;
  450.  
  451.     if( (lb->layer==4)  ||
  452.         (lb->br_ind==0) ||
  453.         (lb->br_ind==15)||
  454.         (lb->freq==3)   )   result+=1;
  455.     if(prevheader)
  456.         if( (currheader&HDR_CONSTANT)!=(prevheader&HDR_CONSTANT) ||
  457.             ((lb->mode==MPG_MD_MONO?1:2)!=channels) ) result+=2;
  458.     if((currheader&HDR_MPEG1)!=HDR_MPEG1) result+=4;
  459.     return(result);
  460. }
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467. /*
  468. **
  469. ** analyze frame header and load frame **
  470. **
  471. */
  472. int ReadFrame(struct loadbuf *lb)
  473. {
  474.     LONG s0,s1,i0,i1;
  475.     UWORD md;
  476.  
  477.     if((md=CheckHeader(lb)))
  478.     {
  479.         if(!prevheader && strict)
  480.         {
  481.             printf("**not recognized as MPEG1 audio\n");
  482.             return(0);
  483.         }
  484.  
  485.         if((currheader&0xffffff00)==ID3V1) printf(" (ID3v1 tag)\n");
  486.         else if(prevheader)
  487.         {
  488.             if(md&4)      printf(" (lost frame sync - non-audio data)\n");
  489.             else if(md&1) printf(" (invalid frame header)\n");
  490.             else if(md&2) printf(" (unsupported frame header change)\n");
  491.             if(verbose)
  492.                 printf("**position=0x%08lx  currheader=0x%08lx  "
  493.                    "prevheader=0x%08lx\n",bytes_loaded,currheader,prevheader);
  494.         }
  495.  
  496.         if(!strict)
  497.         {
  498.             s0=0;
  499.             while((s0<32*1024) && md)
  500.             {
  501.                 bytes_loaded++; s0++;
  502.                 currheader<<=8;
  503.                 i0=ReadCharAsync(file);
  504.                 if(i0<0) break;
  505.                 else
  506.                 {
  507.                     currheader|=i0;
  508.                     md=CheckHeader(lb);
  509.                 }
  510.             }
  511.             printf("**skipped %d bytes - resync %s.\n",s0,md?"failed":"ok");
  512.         }
  513.  
  514.         if(md) return(0);   /* resync failed */
  515.     }
  516.  
  517.  
  518.     if(channels==0) channels=(lb->mode==MPG_MD_MONO)?1:2;
  519.     lb->II_translate= mpg_translate [lb->freq]
  520.                                     [(lb->mode==MPG_MD_MONO)?1:0]
  521.                                     [lb->br_ind];
  522.     lb->II_jsbound= (lb->mode==MPG_MD_JOINT_STEREO) ?
  523.                             (lb->modext<<2)+4 : mpg_sblimit[lb->II_translate];
  524.  
  525.     lb->framesize = (mpg_bitrate[lb->layer-1][lb->br_ind]*144000)
  526.                     /mpg_freq[lb->freq] + ((currheader>>9)&0x1); /* padding */
  527.     lb->delfcopysize = lb->framesize-4;
  528.  
  529.     s0=i0=2;
  530.     if(lb->errprot)
  531.     {
  532.         i0=ReadAsync(file,&lb->crc,s0);
  533.         lb->delfcopysize-=s0;
  534.     }
  535.     s1=i1=lb->delfcopysize;
  536.  
  537.     /** do not read layer I frame because it might be too large !! **/
  538.     if(lb->layer>1) i1=ReadAsync(file,&lb->data[0],s1);
  539.  
  540.  
  541.     /*** at beginning of file: try to recognize the second frame, too ***/
  542.     if(!prevheader)
  543.     {
  544.         /** seek over first layer I frame (it has not been read) **/
  545.         if(lb->layer==1) i1=SeekAsync(file,s1,MODE_CURRENT);
  546.         if(PeekAsync(file,&currheader,4)==4)
  547.         {
  548.             ULONG ch=currheader;
  549.             prevheader=currheader;
  550.             if(CheckHeader(lb->next))
  551.             {
  552.                 printf("** !!! not recognized as MPEG1 audio\n");
  553.                 return(0);
  554.             }
  555.             prevheader=0;
  556.             currheader=ch;
  557.         }
  558.     }
  559.  
  560.  
  561.     if(!((i0==s0) && (i1==s1)))
  562.     {
  563.         if((i0==-1) || (i1==-1))
  564.             printf(" (file read error)\n");
  565.         else
  566.             if(verbose) printf(" (unexpected EOF - got %d of %d bytes)\n",i1,s1);
  567.         return(0);
  568.     }
  569.  
  570.     if(lb->layer==3)
  571.     {
  572.         gb_pt= (UWORD*)&lb->data[2]; gb_num=0;
  573.         if(lb->mode==MPG_MD_MONO)
  574.         {
  575.             GetBits(9+5+4-16);
  576.             md=GetBits(12);
  577.         }
  578.         else
  579.         {
  580.             GetBits(9+3+8-16);
  581.             md=GetBits(12);
  582.             GetBits(59-12);
  583.             md+=GetBits(12);
  584.             GetBits(59-12);
  585.             md+=GetBits(12);
  586.         }
  587.         GetBits(59-12);
  588.         md+=GetBits(12);
  589.         lb->III_main_data_size=(md+7)>>3;
  590.  
  591.         if(lb->mode!=MPG_MD_JOINT_STEREO) lb->modext=0;
  592.         if(lb->modext&1) frames_js++;
  593.  
  594.         if(buffers_filled==0) BitReservoir(lb);
  595.     }
  596.  
  597.     buffers_filled++;
  598.     frames_loaded++;
  599.     bytes_loaded+=lb->framesize;
  600.  
  601.     return(1);
  602. }
  603.  
  604.  
  605.  
  606.  
  607.  
  608.  
  609. void setPosition(ULONG seconds)     /*** WARNING: quick & dirty hack !! ***/
  610. {
  611.     int loop,maxl;
  612.     if(strict) return;
  613.  
  614.     pause++;
  615.     if(seconds>rexxduration) seconds=rexxduration;
  616.   /*printf("----setPosition %d\n",seconds);*/
  617.  
  618.     if(xing_flags&XING_FLAG_TOC)
  619.     {
  620.         /*interpolate in TOC to get file seek point in bytes*/
  621.         int a;
  622.         float fa, fb, fx;
  623.         fx=100.0*(float)seconds/(float)rexxduration;
  624.         a=(int)fx;  if(a>99) a=99;
  625.         fa=xing_toc[a];  
  626.         if(a<99) fb=xing_toc[a+1]; else fb=256.0;
  627.         fx=(fa+(fb-fa)*(fx-a))/256.0;
  628.         bytes_loaded=(int)(fx*bytes_total); 
  629.         frames_loaded=frames_played=seconds*freq/1152;
  630.       /*printf("----Xing VBR new pos: %ld of %ld bytes\n",bytes_loaded,bytes_total);*/
  631.     }
  632.     else
  633.     {
  634.         bytes_loaded=setpos_start+(seconds*(bytes_total-setpos_start))/rexxduration;
  635.         frames_loaded=frames_played=bytes_loaded/setpos_framesize;
  636.       /*printf("----plain new pos: %ld of %ld bytes\n",bytes_loaded,bytes_total);*/
  637.     }
  638.  
  639.     curr_load=curr_play=framebuf0;
  640.     buffers_filled=0;
  641.     bitres_offset=0;
  642.  
  643.     SeekAsync(file,bytes_loaded,MODE_START);
  644.     maxl=((framebuf>8) ? 8 : framebuf);
  645.     for(loop=0; loop<maxl; loop++)
  646.     {
  647.         ReadAsync(file,&currheader,4);
  648.         if(ReadFrame(curr_load))
  649.         {
  650.             prevheader=currheader;
  651.             curr_load=curr_load->next;
  652.         }
  653.         else {bytes_loaded=bytes_total; break;}
  654.     }
  655.     pause--;
  656. }
  657.  
  658.  
  659.  
  660.  
  661.  
  662.     
  663.  
  664.  
  665. int main(void)
  666. {
  667.     struct RDArgs *rdargs;
  668.     LONG args[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, r1, i, taskpri;
  669.     UBYTE **files_pt, *filename;
  670.     double duration, duration2;
  671.     ULONG sigs, minutes, seconds, millisec, curr_print_pos, prev_print_pos;
  672.     struct timeval time1,time2;
  673.     struct rtFileRequester *rtfilereq=NULL;
  674.     struct rtFileList *rtfilelist=NULL, *rtfilelist_curr=NULL;
  675.     BPTR lock_newdir=NULL, lock_olddir=NULL;
  676.  
  677.     /*
  678.     **
  679.     ** read args **
  680.     **
  681.     */
  682.     rdargs=ReadArgs(template,args,NULL);
  683.     printf("\33[1m%s by Smack/Infect!\33[0m\n",&version[6]);
  684.     files_pt=(char**)args[0];
  685.     verbose=args[1];
  686.     noplay=args[2];
  687.     showtag=args[3];
  688.     nofastl=args[4];
  689.     nofastp=args[5];
  690.     if(args[6]) framebuf=(*(LONG*)args[6]); else framebuf=DEFAULT_FRAMEBUF;
  691.     if(args[7]) asyncbuf=(*(LONG*)args[7]); else asyncbuf=DEFAULT_ASYNCBUF;
  692.     if(args[8]) ffskip=(*(LONG*)args[8]); else ffskip=DEFAULT_FFSKIP;
  693.     notimer=args[9];
  694.     forcemono=args[10];
  695.     strict=args[11];
  696.     if(args[12]) dacrate=(*(LONG*)args[12]); else dacrate=0;
  697.     if(args[13]) volume=(*(LONG*)args[13]); else volume=100;
  698.     rexxmode=args[14];
  699.  
  700.     if(verbose)
  701.         printf(
  702.         "\n"
  703.         "  DelfMPEG - MPEG audio player for Delfina DSP\n"
  704.         "  Copyright (C) 1999, 2000  Michael Henke\n"
  705.         "\n"
  706.         "  This program is free software; you can redistribute it and/or modify\n"
  707.         "  it under the terms of the GNU General Public License as published by\n"
  708.         "  the Free Software Foundation; either version 2 of the License, or\n"
  709.         "  (at your option) any later version.\n"
  710.         "\n"
  711.         "  This program is distributed in the hope that it will be useful,\n"
  712.         "  but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  713.         "  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  714.         "  GNU General Public License for more details.\n"
  715.         "\n"
  716.         "  You should have received a copy of the GNU General Public License\n"
  717.         "  along with this program; if not, write to the Free Software\n"
  718.         "  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
  719.         "\n"  );
  720.  
  721.  
  722.     /*
  723.     **
  724.     ** open libraries & stuff **
  725.     **
  726.     */
  727.     if(!noplay)
  728.     {
  729.         ULONG delfina_model;
  730.         double delfina_dspclock;
  731.         if (!(DelfinaBase=OpenLibrary("delfina.library",4)))
  732.         {
  733.             printf("**unable to open delfina.library V4\n");
  734.             rc=20;
  735.             goto exit_clean;
  736.         }
  737.         delfina_model=Delf_GetAttr(DA_HWInfo,0);
  738.         delfina_model&=0xff; i=0;
  739.         while(delfina_model) { delfina_model>>=1; i++; }
  740.         delfina_model=i ? (i-1) : 7;
  741.         if((DelfinaBase->lib_Version==4) && (DelfinaBase->lib_Revision<12))
  742.             delfina_dspclock=0.0;
  743.         else
  744.             delfina_dspclock=(double)Delf_GetAttr(DA_DSPClock,0)/1000000.0;
  745.         if(verbose)
  746.             printf("\n  Delfina %s: delfina.library v%d.%d, %d K memory, %.1f MHz DSP\n",
  747.                    delfina_name[delfina_model],
  748.                    DelfinaBase->lib_Version,
  749.                    DelfinaBase->lib_Revision,
  750.                    (Delf_AvailMem(DMEMF_PROG|DMEMF_TOTAL)+Delf_AvailMem(DMEMF_YDATA|DMEMF_TOTAL)+1023)>>10,
  751.                    delfina_dspclock );
  752.     }
  753.     if (!(AsyncIOBase=OpenLibrary("asyncio.library",39))) {
  754.         printf("**unable to open asyncio.library V39\n");
  755.         rc=20;
  756.         goto exit_clean;
  757.     }
  758.     TimerBase=(struct Library*)FindName(&SysBase->DeviceList,"timer.device");
  759.     mytask=FindTask(NULL);
  760.     if(!(fib=AllocDosObject(DOS_FIB,&tag_done)))
  761.     {
  762.         rc=20;
  763.         goto exit_clean;
  764.     }
  765.     if(rexxmode)
  766.     {
  767.         char *res;
  768.         if((res=initRexx()))
  769.         {
  770.             printf("**initRexx failed (%s)\n",res);
  771.             rc=20;
  772.             goto exit_clean;
  773.         }
  774.     }
  775.         
  776.  
  777.     /*
  778.     **
  779.     ** init load buffers **
  780.     **
  781.     */
  782.     if(framebuf<4) framebuf=4;
  783.     if(asyncbuf<4) asyncbuf=4;
  784.     if(ffskip<1) ffskip=1;
  785.     if(dacrate<0) dacrate=0;
  786.     if(dacrate>48) dacrate=48;
  787.     if(dacrate) dacrate=Delf_GetAttr(DA_Freq,dacrate*1000)/1000;
  788.     if(volume<0) volume=0;
  789.     if(volume>200) volume=200;
  790.     framebuf0size=framebuf*(LONG)sizeof(struct loadbuf);
  791.     if(verbose)
  792.         printf( "\n   reader: framebuf=%d (%d K), asyncbuf=%d K, ffskip=%d, strict=o%s\n"
  793.                 "  decoder: forcemono=o%s, dacrate=%d kHz, volume=%d%%\n",
  794.                 framebuf, (framebuf0size+1023)>>10, asyncbuf, ffskip, strict?"n":"ff",
  795.                 forcemono?"n":"ff", dacrate, volume );
  796.     if(!(framebuf0=(struct loadbuf*)AllocMem(framebuf0size,MEMF_PUBLIC)))
  797.     {
  798.         printf("**not enough memory for \"framebuf\"\n");
  799.         rc=20;
  800.         goto exit_clean;
  801.     }
  802.     for(i=0;i<framebuf-1;i++) framebuf0[i].next= &framebuf0[i+1];
  803.     framebuf0[framebuf-1].next=framebuf0;
  804.  
  805.  
  806.     /*
  807.     **
  808.     ** reqtools filerequester if no files specified **
  809.     **
  810.     */
  811.     if(!files_pt && !rexxmode)
  812.     {
  813.         if((ReqToolsBase=(struct ReqToolsBase*)OpenLibrary("reqtools.library",38)))
  814.         {
  815.             if(!(rtfilereq=rtAllocRequest(RT_FILEREQ,NULL)))
  816.             {
  817.                 rc=10;
  818.                 goto exit_clean;
  819.             }
  820.         }
  821.         else
  822.         {
  823.             rc=5;
  824.             goto exit_clean;
  825.         }
  826.     }
  827.  
  828.     rexxduration=rexxposition=0;
  829.     pause=1; rexxerror=0;   /* initialize */
  830.  
  831. next_filereq:
  832.     if(rtfilereq)
  833.     {
  834.         rtfilelist=rtFileRequest( rtfilereq, &rtfilename[0],
  835.                                   "DelfMPEG: select MPEG audio files",
  836.                                   RTFI_Flags, FREQF_MULTISELECT|FREQF_PATGAD,
  837.                                   TAG_DONE );
  838.         if(rtfilelist)
  839.         {
  840.             rtfilelist_curr=rtfilelist;
  841.             if(rtfilereq->Dir)
  842.             {
  843.                 lock_newdir=Lock(rtfilereq->Dir,SHARED_LOCK);
  844.                 lock_olddir=CurrentDir(lock_newdir);
  845.             }
  846.         }
  847.         else goto exit_clean;
  848.     }
  849.  
  850. next_rexxloop:
  851.     if(rexxmode)
  852.     {
  853.         ende=1; rexxstatus=0;   /* status: stop */
  854.         rexxfilename[0]=NULL;
  855.         printf("\n  ARexx mode: waiting for 'PLAY <file>' on port '%s'\n",portname);
  856.         while(!rexxfilename[0])
  857.         {
  858.             handleRexx();
  859.             if(CheckSignal(SIGBREAKF_CTRL_D)) goto exit_clean;
  860.             if(ende>1) goto exit_clean;     /* QUIT command */
  861.             Delay(1);
  862.         }
  863.         files_pt=rexxfilename;
  864.         rexxduration=rexxposition=0;
  865.         rexxfiletypebuf[0]=0;
  866.         rexxerror=0;                /* PLAY command clears rexxerror */
  867.         rexxstatus=1;               /* status: play */
  868.         if(pause>1) rexxstatus=2;   /* status: pause */
  869.     }
  870.     ende=0;
  871.  
  872.     /*
  873.     **
  874.     ** files loop **
  875.     **
  876.     */
  877.     do
  878.     {
  879.         /*
  880.         **
  881.         ** get next filename **
  882.         **
  883.         */
  884.         if(rtfilelist)
  885.         {
  886.             if(rtfilelist_curr)
  887.             {
  888.                 filename=rtfilelist_curr->Name;
  889.                 rtfilelist_curr=rtfilelist_curr->Next;
  890.             }
  891.             else filename=NULL;
  892.         }
  893.         else filename=(*files_pt++);
  894.         if(!filename) break;
  895.         printf("\n  file: %s\n",filename);
  896.  
  897.         havetag=0;
  898.         setpos_start=prev_print_pos=curr_print_pos=0;
  899.         curr_load=curr_play=framebuf0;
  900.         bytes_loaded=buffers_filled=buffers_missed=0;
  901.         prevheader=currheader=channels=0;
  902.         frames_loaded=frames_played=0;
  903.         decoder_busy=maindata_err=frames_js=0;
  904.         bitres_offset=0;
  905.  
  906.         /*
  907.         **
  908.         ** open file **
  909.         **
  910.         */
  911.         rexxerror=20;  /* file not found */
  912.         if((file=OpenAsync(filename,MODE_READ,asyncbuf<<10)))
  913.         {
  914.             /*
  915.             **
  916.             ** read first frame + output some info **
  917.             **
  918.             */
  919.             ExamineFH(file->af_File,fib);
  920.             bytes_total=fib->fib_Size;
  921.             ReadAsync(file,&currheader,4);
  922.  
  923.             if(currheader==0x52494646)          /* RIFF WAVE header */
  924.             {
  925.                 UBYTE b[8];
  926.                 ReadAsync(file,&b[0],8);
  927.                 r1=20;  /* 12+8 bytes */
  928.                 while(1)
  929.                 {
  930.                     if(ReadAsync(file,&b[0],8)!=8)   /* chunk name + length */
  931.                         break;  /* EOF -> ReadFrame() detects this */
  932.                     r1=((LONG)b[7]<<24)|((LONG)b[6]<<16)|((LONG)b[5]<<8)|(LONG)b[4];
  933.                     if((b[0]=='d')&&(b[1]=='a')&&(b[2]=='t')&&(b[3]=='a'))
  934.                         break;                       /* found data chunk */
  935.                     SeekAsync(file,r1,MODE_CURRENT); /* skip unknown chunk */
  936.                 }
  937.                 bytes_total=r1;
  938.                 if(verbose)
  939.                     printf("  found RIFF header (data chunk: %ld bytes)\n",r1);
  940.                 ReadAsync(file,&currheader,4);
  941.             }
  942.  
  943.             if((currheader&0xFFFFFF00)==ID3V2)  /* found ID3V2 tag */
  944.             {
  945.                 UBYTE b[6];
  946.                 ReadAsync(file,&b[0],6);
  947.                 r1=(LONG)b[5]|((LONG)b[4]<<7)|((LONG)b[3]<<14)|((LONG)b[2]<<21);
  948.                 SeekAsync(file,r1,MODE_CURRENT);
  949.                 r1+=10;
  950.                 if(verbose)
  951.                     printf("  skipped ID3v2.%d.%d tag (%d bytes)\n",
  952.                             currheader&0xFF, b[0], r1);
  953.                 bytes_loaded+=r1;
  954.                 ReadAsync(file,&currheader,4);
  955.             }
  956.  
  957.             rexxerror=30;  /* file not recognized as MPEG1 audio */
  958.             if(ReadFrame(curr_load))    /* recognize the MPEG audio file */
  959.             {
  960.                 if(showtag)
  961.                 {
  962.                     LONG oldpos;
  963.                     oldpos=SeekAsync(file, -128, MODE_END);
  964.                     ID3v1_TAG=0; havetag=0;
  965.                     ReadAsync(file, &ID3v1_TAG, 3);
  966.                     if((ID3v1_TAG&0xffffff00)==ID3V1)
  967.                     {
  968.                         ReadAsync(file,&ID3v1_buffer[00],30); /* title  */
  969.                         ReadAsync(file,&ID3v1_buffer[31],30); /* artist */
  970.                         ReadAsync(file,&ID3v1_buffer[62],30); /* album  */
  971.                         ReadAsync(file,&ID3v1_buffer[93],04); /* year   */
  972.                         ReadAsync(file,&ID3v1_buffer[98],30); /* comment*/
  973.                         ReadAsync(file,&ID3v1_buffer[141],1); /* genre  */
  974.                         for(i=0;i<140;i++)
  975.                         {
  976.                             if(ID3v1_buffer[i]<0x20) ID3v1_buffer[i]=0x20;
  977.                         }
  978.                         ID3v1_buffer[30]=0x00;
  979.                         ID3v1_buffer[30+1+30]=0x00;
  980.                         ID3v1_buffer[30+1+30+1+30]=0x00;
  981.                         ID3v1_buffer[30+1+30+1+30+1+4]=0x00;
  982.                         ID3v1_buffer[30+1+30+1+30+1+4+1+30]=0x00;
  983.                         havetag=1;
  984.                     }
  985.                     SeekAsync(file, oldpos, MODE_START);
  986.                 }
  987.  
  988.                 {   /* look for Xing VBR header */
  989.                     UBYTE *xpt;
  990.                     xingvbr=xing_flags=0;
  991.                     xpt= &curr_load->data[0];
  992.                     xpt+=(curr_load->mode==MPG_MD_MONO) ? 17 : 32;
  993.                     if((xpt[0]=='X') &&
  994.                        (xpt[1]=='i') &&
  995.                        (xpt[2]=='n') &&
  996.                        (xpt[3]=='g') )
  997.                     {
  998.                         xingvbr++;
  999.                         xpt+=4;
  1000.                         xing_flags= (ULONG)xpt[0]<<24 | (ULONG)xpt[1]<<16 |
  1001.                                     (ULONG)xpt[2]<<8  | (ULONG)xpt[3];
  1002.                         xpt+=4;
  1003.                         if(xing_flags&XING_FLAG_FRAMES)
  1004.                         {
  1005.                             xing_frames=(ULONG)xpt[0]<<24 | (ULONG)xpt[1]<<16 |
  1006.                                         (ULONG)xpt[2]<<8  | (ULONG)xpt[3];
  1007.                             xpt+=4;
  1008.                         }
  1009.                         else xing_frames=0;
  1010.                         if(xing_flags&XING_FLAG_BYTES) xpt+=4;
  1011.                         if(xing_flags&XING_FLAG_TOC)
  1012.                         {
  1013.                             for(i=0;i<100;i++) xing_toc[i]=xpt[i];
  1014.                         }
  1015.                         if(verbose) printf("  Xing VBR header found (info: %d frames, TOC=%s)\n",xing_frames,((xing_flags&XING_FLAG_TOC)?"yes":"no"));
  1016.  
  1017.                     }
  1018.                 }
  1019.  
  1020.                 freq=mpg_freq[curr_load->freq];
  1021.                 mono=(curr_load->mode==MPG_MD_MONO) ? 1 : 0;
  1022.                 layer=curr_load->layer;
  1023.                 setpos_framesize=curr_load->framesize;
  1024.  
  1025.                 duration=(double)bytes_total/((double)freq/1152.0)/(double)curr_load->framesize;
  1026.                 r1=mpg_bitrate[layer-1][curr_load->br_ind];
  1027.                 if(xingvbr && xing_frames)
  1028.                 {
  1029.                     duration=(double)xing_frames*1152.0/(double)freq;
  1030.                     r1=(LONG)((double)bytes_total/duration/125.0);
  1031.                 }
  1032.                 sprintf(rexxfiletypebuf,
  1033.                         "layer %s  %s%03d kbps  %ld Hz  %s",
  1034.                         mpg_layername[layer-1],
  1035.                         (xingvbr && xing_frames) ? "VBR avg. " : "",
  1036.                         r1,
  1037.                         freq,
  1038.                         mpg_modename[curr_load->mode] );
  1039.                 printf("  type: %s\n",rexxfiletypebuf);
  1040.                 rexxduration=(ULONG)(duration+0.5);
  1041.                 millisec=(ULONG)(1000.0*modf(duration,&duration2));
  1042.                 minutes=(ULONG)(duration2/60.0);
  1043.                 seconds=(ULONG)(duration2-minutes*60.0);
  1044.                 printf("  time: %02ld min %02ld.%03ld sec\n",minutes,seconds,millisec);
  1045.                 if(verbose) printf("  filesize/framesize: %ld/%ld bytes\n",bytes_total,curr_load->framesize);
  1046.  
  1047.                 if(showtag && havetag)
  1048.                 {
  1049.                     printf( "  TAG ID3v1\n      title: %s\n     artist: %s\n"
  1050.                             "      album: %s\n    comment: %s\n"
  1051.                             "       year: %s    genre: %d\n",
  1052.                             &ID3v1_buffer[00], /* title  */
  1053.                             &ID3v1_buffer[31], /* artist */
  1054.                             &ID3v1_buffer[62], /* album  */
  1055.                             &ID3v1_buffer[98], /* comment*/
  1056.                             &ID3v1_buffer[93], /* year   */
  1057.                             (int)ID3v1_buffer[141] ); /* genre  */
  1058.                 }
  1059.  
  1060.                 prevheader=currheader;
  1061.                 curr_load=curr_load->next;
  1062.  
  1063.                 rexxerror=10;  /* initDelfina failed */
  1064.                 if(InitDelfina())
  1065.                 {
  1066.                     rexxerror=0;    /* ok */
  1067.                     printf("  playing..."); fflush(stdout);
  1068.                     taskpri=SetTaskPri(mytask,9);
  1069.                     GetSysTime(&time1);
  1070.                     if(pause>0) pause--;
  1071.                     /*
  1072.                     **
  1073.                     ** frames loop **
  1074.                     **
  1075.                     */
  1076.                     while(!ende)
  1077.                     {
  1078.                         if(rexxmode) handleRexx();
  1079.                         sigs=CheckSignal(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F);
  1080.                         if(sigs&SIGBREAKF_CTRL_C)
  1081.                         {
  1082.                             printf(" break CTRL-C\n");
  1083.                             break;  /* exit frames loop */
  1084.                         }
  1085.                         if(sigs&SIGBREAKF_CTRL_D)
  1086.                         {
  1087.                             ende=2;
  1088.                             printf(" break CTRL-D\n");
  1089.                             break;  /* exit frames loop */
  1090.                         }
  1091.                         if(sigs&SIGBREAKF_CTRL_E)
  1092.                         {
  1093.                             if(pause)
  1094.                             {
  1095.                                 pause=0;
  1096.                                 rexxstatus=1;   /* play */
  1097.                                 printf("\n  playing...");
  1098.                             }
  1099.                             else
  1100.                             {
  1101.                                 pause=1;
  1102.                                 rexxstatus=2;   /* pause */
  1103.                                 printf(" pause");
  1104.                             }
  1105.                             fflush(stdout);
  1106.                         }
  1107.                         if(sigs&SIGBREAKF_CTRL_F)
  1108.                         {
  1109.                             pause++;
  1110.                             i=ffskip;
  1111.                             while((buffers_filled>0) && (i>0))
  1112.                             {
  1113.                                 curr_play=curr_play->next;
  1114.                                 buffers_filled--; i--;
  1115.                                 frames_played++;
  1116.                                 if((layer==3) && (buffers_filled>0))
  1117.                                     BitReservoir(curr_play);
  1118.                             }
  1119.                             pause--;
  1120.                         }
  1121.                         if( (buffers_filled<framebuf) &&
  1122.                             (bytes_loaded<bytes_total) )
  1123.                         {
  1124.                             if(ReadAsync(file,&currheader,4)==4)
  1125.                                 if(ReadFrame(curr_load))
  1126.                                 {
  1127.                                     prevheader=currheader;
  1128.                                     curr_load=curr_load->next;
  1129.                                 }
  1130.                                 else bytes_loaded=bytes_total; /* force EOF */
  1131.                             else bytes_loaded=bytes_total;
  1132.                         }
  1133.                         else
  1134.                         {
  1135.                             if( (bytes_loaded>=bytes_total) &&
  1136.                                 (buffers_filled==0) )
  1137.                             {
  1138.                                 printf(" done.\n");
  1139.                                 break;  /* exit frames loop */
  1140.                             }
  1141.  
  1142.                             if(!notimer)    /* print timer */
  1143.                             {
  1144.                                 curr_print_pos=(frames_played*1152)/freq;
  1145.                                 if(prev_print_pos!=curr_print_pos)
  1146.                                 {
  1147.                                     rexxposition=curr_print_pos;
  1148.                                     prev_print_pos=curr_print_pos;
  1149.                                     printf("\r  playing... (%02d:%02d)",
  1150.                                         curr_print_pos/60, curr_print_pos%60);
  1151.                                     fflush(stdout);
  1152.                                 }
  1153.                             }
  1154.                             Delay(1);
  1155.                         }
  1156.                     }
  1157.                     pause++; /* mute output */
  1158.                     GetSysTime(&time2);
  1159.                     SetTaskPri(mytask,taskpri);
  1160.                     SubTime(&time2,&time1);
  1161.                     millisec=(ULONG)((double)time2.tv_micro/1000.0);
  1162.                     minutes=(ULONG)((double)time2.tv_secs/60.0);
  1163.                     seconds=(ULONG)((double)time2.tv_secs-minutes*60.0);
  1164.                     duration2=(double)time2.tv_secs+(double)time2.tv_micro/1000000.0;
  1165.                     if(verbose)
  1166.                     {
  1167.                         if(buffers_missed>5) /* prevent "unnecessary" warnings */
  1168.                             printf("**note: detected NO_INPUT_DATA %d times\n",buffers_missed);
  1169.                         if(decoder_busy>0)
  1170.                             printf("**note: detected DECODER_BUSY %d times (%d%%)\n",decoder_busy,decoder_busy*100/frames_played);
  1171.                         if(maindata_err>0)
  1172.                             printf("**note: detected MP3_MAINDATA_ERROR %d times\n",maindata_err);
  1173.                         if(frames_js>0)
  1174.                             printf("**note: unsupported INTENSITY_STEREO frames: %d (%d%%)\n",frames_js,frames_js*100/frames_loaded);
  1175.                         printf("  frames played/loaded: %ld/%ld\n",frames_played,frames_loaded);
  1176.                         printf("  elapsed time: %02ld min %02ld.%03ld sec\n",minutes, seconds, millisec);
  1177.                     }
  1178.                 }
  1179.                 CleanupDelfina();
  1180.             }
  1181.             CloseAsync(file);
  1182.         }
  1183.         else printf("**unable to open file\n");
  1184.     } while(!ende);
  1185.  
  1186.     if(rtfilelist)
  1187.     {
  1188.         if(lock_olddir) { CurrentDir(lock_olddir); lock_olddir=NULL; }
  1189.         if(lock_newdir) { UnLock(lock_newdir); lock_newdir=NULL; }
  1190.         rtFreeFileList(rtfilelist); rtfilelist=NULL;
  1191.         if(ende<2) goto next_filereq;
  1192.     }
  1193.     if(rexxmode && (ende<2)) goto next_rexxloop;
  1194.  
  1195. exit_clean:
  1196.     cleanupRexx();
  1197.     if(rdargs) FreeArgs(rdargs);
  1198.     if(framebuf0) FreeMem((APTR)framebuf0,framebuf0size);
  1199.     if(fib) FreeDosObject(DOS_FIB,fib);
  1200.     if(rtfilereq) rtFreeRequest(rtfilereq);
  1201.     if(ReqToolsBase) CloseLibrary((struct Library*)ReqToolsBase);
  1202.     if(AsyncIOBase) CloseLibrary(AsyncIOBase);
  1203.     if(DelfinaBase) CloseLibrary(DelfinaBase);
  1204.     return(rc);
  1205. }
  1206.